package com.example.dell.fastshopping.network;

import android.content.Context;
import android.text.TextUtils;

import com.example.dell.fastshopping.network.http.BaseResponse;
import com.example.dell.fastshopping.network.http.BaseSubscriber;
import com.example.dell.fastshopping.network.http.ResponseThrowable;
import com.example.dell.fastshopping.network.http.cookie.CookieJarImpl;
import com.example.dell.fastshopping.network.http.cookie.store.PersistentCookieStore;
import com.example.dell.fastshopping.network.http.interceptor.BaseInterceptor;
import com.example.dell.fastshopping.network.http.interceptor.CaheInterceptor;
import com.example.dell.fastshopping.network.http.interceptor.ResponseInterceptor;
import com.example.dell.fastshopping.network.http.interceptor.logging.Level;
import com.example.dell.fastshopping.network.http.interceptor.logging.LoggingInterceptor;
import com.example.dell.fastshopping.utils.KLog;
import com.example.dell.fastshopping.utils.Utils;
import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;

import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.observers.DisposableObserver;
import io.reactivex.schedulers.Schedulers;

import okhttp3.Cache;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import okhttp3.internal.platform.Platform;
import retrofit2.HttpException;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by goldze on 2017/5/10.
 * RetrofitClient封装单例类, 实现网络请求
 */
public class RetrofitClient {
    //超时时间
    private static final int DEFAULT_TIMEOUT = 20;
    //缓存时间
    private static final int CACHE_TIMEOUT = 10 * 1024 * 1024;
    //服务端根路径
    public static String baseUrl = "http://devjinpai.hz-huanshi.com/auction/";
   //  public static String baseUrl = "http://192.168.10.100:8080/auction/";
    // public static String baseUrl = "http://192.168.10.63:8080/auction/";

    private static Context mContext = Utils.getContext();

    private static OkHttpClient okHttpClient;
    private static Retrofit retrofit;

    private Cache cache = null;
    private File httpCacheDirectory;

    private static RetrofitClient INSTANCE;


    public static RetrofitClient getInstance() {
        if (INSTANCE == null) {
            synchronized (RetrofitClient.class) {
                if (INSTANCE == null) {
                    INSTANCE = new RetrofitClient();
                }
                return INSTANCE;
            }
        }
        return INSTANCE;
    }

    private static RetrofitClient getInstance(String url) {

        return new RetrofitClient(url);
    }

    private static RetrofitClient getInstance(String url, Map<String, String> headers) {
        return new RetrofitClient(url, headers);
    }

    private RetrofitClient() {
        this(baseUrl, null);
    }

    private RetrofitClient(String url) {
        this(url, null);
    }

    private RetrofitClient(String url, Map<String, String> headers) {

        if (TextUtils.isEmpty(url)) {
            url = baseUrl;
        }

        if (httpCacheDirectory == null) {
            httpCacheDirectory = new File(mContext.getCacheDir(), "goldze_cache");
        }

        try {
            if (cache == null) {
                cache = new Cache(httpCacheDirectory, CACHE_TIMEOUT);
            }
        } catch (Exception e) {
            KLog.e("Could not create http cache", e);
        }

        okHttpClient = new OkHttpClient.Builder()
                .cookieJar(new CookieJarImpl(new PersistentCookieStore(mContext)))
//                .cache(cache)
                .addInterceptor(new BaseInterceptor(headers))
                .addInterceptor(new CaheInterceptor(mContext))
                .addInterceptor(new ResponseInterceptor(mContext))
                .addInterceptor(new LoggingInterceptor
                        .Builder()//构建者模式
                        .loggable(true) //是否开启日志打印
                        .setLevel(Level.BODY) //打印的等级
                        .log(Platform.INFO) // 打印类型
                        .request("Request") // request的Tag
                        .response("Response")// Response的Tag
                        // .addHeader("version", BuildConfig.VERSION_NAME)//打印版本
                        .build()
                )
                .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .connectionPool(new ConnectionPool(8, 15, TimeUnit.SECONDS))
                // 这里你可以根据自己的机型设置同时连接的个数和时间，我这里8个，和每个保持时间为10s
                .build();
        retrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl(url)
                .build();

    }

    /**
     * create you ApiService
     * Create an implementation of the API endpoints defined by the {@code service} interface.
     */
    public <T> T create(final Class<T> service) {
        if (service == null) {
            throw new RuntimeException("Api service is null!");
        }
        return retrofit.create(service);
    }

    /**
     * /**
     * execute your customer API
     * For example:
     * MyApiService service =
     * RetrofitClient.getInstance(MainActivity.this).create(MyApiService.class);
     * <p>
     * RetrofitClient.getInstance(MainActivity.this)
     * .execute(service.lgon("name", "password"), subscriber)
     * * @param subscriber
     */

    public static <T> T execute(Observable<T> observable, Observer<T> subscriber) {
        observable.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);

        return null;
    }

    public static <T> T execute(Observable<T> observable, Consumer<T> consumer, Consumer<Throwable> throwable) {
        observable.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(consumer, throwable);
        return null;
    }

    public static void execute(Observable observable, final NetCallback callback) {

        observable.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new BaseSubscriber(Utils.getContext()) {
                    @Override
                    public void onResult(BaseResponse o) {
                        callback.netCallback(o);
                    }

                    @Override
                    public void onError(ResponseThrowable e) {

                    }
                });
    }

    public static void executeBackAll(Observable observable, final NetCallback callback) {

        observable.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new DisposableObserver() {

                    @Override
                    public void onNext(Object b) {
                        BaseResponse baseResponse;
                        if (b instanceof LinkedTreeMap) {
                            KLog.e("LinkedTreeMap");
                            LinkedTreeMap treeMap = (LinkedTreeMap) b;
                            if (treeMap.get("data") == null) {
                                baseResponse = new BaseResponse(treeMap.get("code") + "", treeMap.get("msg") + "");
                            } else {
                                baseResponse = (BaseResponse) b;
                            }
                        } else {
                            baseResponse = (BaseResponse) b;
                        }
                        callback.netCallback(baseResponse);
                    }

                    @Override
                    public void onError(Throwable e) {
                        //  KLog.e(e.toString());
                        if (e instanceof HttpException) {
                            HttpException exception = (HttpException) e;
                            if (exception.code() == 500) {
                                ResponseBody responseBody = exception.response().errorBody();
                                if (responseBody != null) {
                                    String json = null;//第一次获取就保存下来
                                    try {
                                        json = responseBody.string();
                                        BaseResponse baseResponse = new Gson().fromJson(json, BaseResponse.class);
                                        callback.netCallback(baseResponse);
                                    } catch (IOException e1) {
                                        e1.printStackTrace();
                                    }

                                }

                            }
                        }
                    }

                    @Override
                    public void onComplete() {
                        KLog.e("onComplete");
                    }
                });
    }
}
